﻿using Xejen.Communication.EthernetIP;
using Xejen.Communication.EthernetIP.Communicator;
using Xejen.Ipc.Framework;
using Xejen.Ipc.Framework.Extensions;
using Xejen.Ipc.Framework.Flows;
using Xejen.Ipc.Framework.Steps;
using Xejen.Ipc.Test.Steps;
using Xejen.Logger.NLog;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Xejen.Ipc.Test
{
    public partial class IocForm : Form
    {
        private IIpcHost _ipcHost;
        protected IFlow<Data> MainFlow;
        private CancellationTokenSource _cancellationTokenSource;
        private readonly IEthernetIpCommunicator _ethernetIpCommunicator;

        public static IocForm Instance;
        public IFlow<Data> Unit7Flow;
        public IFlow<Data> Unit8Flow;

        private readonly System.Timers.Timer _timer;

        public IocForm(IIpcHost host, IEthernetIpCommunicator ethernetIpCommunicator)
        {
            _ipcHost = host;
            _ethernetIpCommunicator = ethernetIpCommunicator;

            InitializeComponent();

            Instance = this;

            _timer = new System.Timers.Timer(10);
            _timer.Elapsed += _timer_Elapsed;
        }

        private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            BeginInvoke(new Action(() =>
            {
                label4.Text = MainFlow.Status.ToString();
            }));
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            //写法1
            var mainFlow = CreateFlow(new IpcHostConfig { ScanIntervalThreshold = 30 }, (factory) =>
            {
                return factory.NewControllerBuilder()
                        .Then(p => p.New<Unit1>("单元1"))
                        .If(data => data.Value >= 10, (data) =>
                        {
                            Debug.WriteLine($"没有触发条件，因为值是{data.Value}");
                        }, p => p.New<Unit2>("单元2"))
                        .Then(p => p.New<Unit3>("单元3"))
                        .All(p => p.New<Unit4>("单元4"), p => p.New<Unit5>("单元5"))
                        .Any(p => p.New<Unit6>("单元6"), p => p.New<Unit7>("单元7"))
                        .Then(p => p.New<Unit8>("单元8"))
                        .Build("主流程");
            });
            //写法2
            //var mainFlow = _ipcHost.CreateFlow<Data>((builder) =>
            // {
            //     builder.Body = (factory) =>
            //     {
            //         return factory
            //         .NewControllerBuilder()
            //         .Then(p => p.New<Unit1>("单元1"))
            //         .If(data => data.Value > 20, (data) =>
            //         {
            //             Debug.WriteLine($"没有触发条件，因为ccd数据为空");
            //         }, p => p.New<Unit2>("单元2"))
            //         .Then(p => p.New<Unit3>("单元3"))
            //         .Any(p => p.New<Unit4>("单元4"), p => p.New<Unit5>("单元5"))
            //         .All(p => p.New<Unit6>("单元6"), p => p.New<Unit7>("单元7"))
            //         .Then(p => p.New<Unit8>("单元8"))
            //         .Build("主流程");
            //     };
            //     builder.Started = (args) => { Debug.WriteLine($"流程启动：{args.Flow.Id} : {args.Flow.Name}"); };
            //     builder.Paused = (args) => { Debug.WriteLine($"流程暂停：{args.Flow.Id} : {args.Flow.Name}"); };
            //     builder.Resumed = (args) => { Debug.WriteLine($"流程恢复：{args.Flow.Id} : {args.Flow.Name}"); };
            //     builder.Stopped = (args) => { Debug.WriteLine($"流程停止：{args.Flow.Id} : {args.Flow.Name}"); };

            //     builder.CycleCompleted += (args) =>
            //     {
            //         SetCycle(args.Flow.CycleExecutionTime);
            //         Print(content);

            //         if (i > 10)
            //         {
            //             content = string.Empty;
            //             i = 0;
            //         }
            //         i++;
            //     };
            //     builder.ScanIntervalExceeded += (args) =>
            //     {
            //         Invoke(new Action(() =>
            //         {
            //             MessageLabel.Text = "扫描周期过长提醒 " + Math.Ceiling(args.ScanInterval.TotalMilliseconds).ToString() + " ms，发生时间在：" + args.Flow.CycleEndTime.Value.ToString("yyyy-MM-dd HH:mm:ss:fff");
            //         }));
            //     };

            //     builder.Execution = (args) =>
            //     {
            //         args.Controllers.ForEach((controller) =>
            //         {
            //             controller.Completed += (s, args1) =>
            //             {
            //                 content += $"子控制器：<{ args1.Controller.Name}> 执行完毕，在 {args1.Controller.CycleEndTime}" + Environment.NewLine;
            //             };

            //             controller.Steps.ForEach((step) =>
            //             {
            //                 step.Completed += (s, args2) =>
            //                 {
            //                     content += $"子步骤：<{ args2.Step.Name}> 执行完毕，在 {args2.Step.CycleEndTime}" + Environment.NewLine;
            //                 };
            //             });
            //         });
            //     };

            //     builder.Error += (args) =>
            //     {
            //         BeginInvoke(new Action(() =>
            //         {
            //             ErrorTextBox.Text = args.Exception.StackTrace
            //             + Environment.NewLine
            //             + "----------------------" + DateTime.Now.ToString() + "-----------------------"
            //             + Environment.NewLine
            //             + ErrorTextBox.Text;
            //         }));
            //     };

            //     return builder.CreateFlow();
            // });


            MainFlow = mainFlow;
            MainFlow.Data.EthernetIpCommunicator = _ethernetIpCommunicator;


            Create7Flow();
            Create8Flow();

            _timer.Start();

        }

        private void Create7Flow()
        {
            IFlow<Data> childFlow1 = _ipcHost.CreateFlowWithFactory<Data>((factory) =>
            {
                return factory.NewControllerBuilder()
                        .Then(p => p.New<ChildUnit1>("子单元1"))
                        .Then(p => p.New<ChildUnit2>("子单元2"))
                        .Then(p => p.New<ChildUnit3>("子单元3"))
                        .Build("子流程7", MainFlow);
            });
            childFlow1.Controllers.ForEach((controller) =>
            {
                controller.Completed += (s, e) =>
                {
                    content += $"子控制器：<{ e.Controller.Name}> 执行完毕，在 {e.Controller.CycleEndTime}" + Environment.NewLine;
                };

                controller.Steps.ForEach((step) =>
                {
                    step.Completed += (s, e) =>
                    {
                        content += $"子步骤：<{ e.Step.Name}> 执行完毕，在 {e.Step.CycleEndTime}" + Environment.NewLine;
                    };
                });
            });

            childFlow1.CycleCompleted += (s, e) =>
            {
                content += $"子流程：<{e.Flow.Id}:{e.Flow.Name}>完成，在 {e.Flow.Parent.Id}>{e.Flow.Parent.Name} { e.Flow.CycleEndTime}" + Environment.NewLine;

            };
            Unit7Flow = childFlow1;
        }
        private void Create8Flow()
        {
            Unit8Flow = _ipcHost.CreateFlowUsingBuilder<Data>((builder) =>
            {
                builder.Body = (factory) =>
                {
                    return factory.NewControllerBuilder()
                            .Then(p => p.New<ChildUnit1>("子单元4"))
                            .Then(p => p.New<ChildUnit2>("子单元5"))
                            .Then(p => p.New<ChildUnit3>("子单元6"))
                            .Build("子流程8", Unit7Flow);
                };
                builder.Execution = (args) =>
                {
                    args.Controllers.ForEach((controller) =>
                    {
                        controller.Completed += (s, e) =>
                        {
                            content += $"子控制器：<{ e.Controller.Name}> 执行完毕，在 {e.Controller.CycleEndTime}" + Environment.NewLine;
                        };

                        controller.Steps.ForEach((step) =>
                        {
                            step.Completed += (s, e) =>
                            {
                                content += $"子步骤：<{ e.Step.Name}> 执行完毕，在 {e.Step.CycleEndTime}" + Environment.NewLine;
                            };
                        });
                    });

                    args.CycleCompleted += (s, e) =>
                    {
                        content += $"子流程：<{e.Flow.Id}:{e.Flow.Name}>完成，在 {e.Flow.Parent.Id}>{e.Flow.Parent.Name} { e.Flow.CycleEndTime}";

                        content = content + Environment.NewLine;

                        Print(content);
                    };
                };

                return builder.CreateFlow();
            });
        }

        string content = string.Empty;
        int i = 0;

        private IFlow<Data> CreateFlow(IpcHostConfig options, Func<IBuilderFactory<Data>, IFlow<Data>> func)
        {
            var flow = _ipcHost.CreateFlowWithFactory(func);
            flow.Started += (sender, args) => { Debug.WriteLine($"流程启动：{args.Flow.Id} : {args.Flow.Name}"); };
            flow.Paused += (sender, args) => { Debug.WriteLine($"流程暂停：{args.Flow.Id} : {args.Flow.Name}"); };
            flow.Resumed += (sender, args) => { Debug.WriteLine($"流程恢复：{args.Flow.Id} : {args.Flow.Name}"); };
            flow.Stopped += (sender, args) => { Debug.WriteLine($"流程停止：{args.Flow.Id} : {args.Flow.Name}"); };
            flow.CycleCompleted += (sender, args) =>
            {
                SetCycle(args.Flow.CycleExecutionTime);
                Print(content);

                if (i > 10)
                {
                    content = string.Empty;
                    i = 0;
                }
                i++;
            };
            flow.ScanIntervalExceeded += (sender, args) =>
            {
                Invoke(new Action(() =>
                {
                    MessageLabel.Text = "扫描周期过长提醒 " + Math.Ceiling(args.ScanInterval.TotalMilliseconds).ToString() + " ms，发生时间在：" + args.Flow.CycleEndTime.Value.ToString("yyyy-MM-dd HH:mm:ss:fff");
                }));
            };
            flow.Controllers.ForEach((controller) =>
            {
                controller.Steps.ForEach((step) =>
                {

                });
            });
            flow.Error += (sender, args) =>
            {
                BeginInvoke(new Action(() =>
                {
                    ErrorTextBox.Text = args.Exception.StackTrace
                    + Environment.NewLine
                    + "----------------------" + DateTime.Now.ToString() + "-----------------------"
                    + Environment.NewLine
                    + ErrorTextBox.Text;
                }));
            };

            return flow;
        }

        /// <summary>
        /// 周期循环处理工作流程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            _cancellationTokenSource = new CancellationTokenSource();
            MainFlow.Start(_cancellationTokenSource.Token);
        }

        /// <summary>
        /// 暂停
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            MainFlow?.Pause();
        }

        /// <summary>
        /// 继续
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            MainFlow?.Resume();
        }

        /// <summary>
        /// 中止
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            MainFlow?.Stop();
        }

        /// <summary>
        /// 取消
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            _cancellationTokenSource?.Cancel();
        }

        /// <summary>
        /// 设置扫描周期
        /// </summary>
        /// <param name="ts"></param>
        public void SetCycle(TimeSpan? ts)
        {
            if (ts == null)
            {
                CycleLabel.Text = string.Empty;
                return;
            }

            if (InvokeRequired)
            {
                BeginInvoke(new Action<TimeSpan?>(SetCycle), ts);
                return;
            }

            CycleLabel.Text = Math.Ceiling(ts.Value.TotalMilliseconds).ToString() + " ms";
        }

        /// <inheritdoc/>
        protected override void OnClosing(CancelEventArgs e)
        {
            _cancellationTokenSource.Cancel();
            _timer.Stop();
            MainFlow?.Stop();

            base.OnClosing(e);
        }

        private void Print(string content)
        {
            BeginInvoke(new Action(() =>
            {
                ErrorTextBox.Text = content;
            }));
        }
    }
}
